# api_gateway/async_routers.py
"""
异步API路由模块
提供异步Agent调用的RESTful接口
"""
import asyncio
from typing import Dict, Any, List
from fastapi import APIRouter, HTTPException, BackgroundTasks, Depends
from pydantic import BaseModel, Field
from loguru import logger

from apps.orchestrator.async_orchestrator_agent import AsyncOrchestratorAgent
from apps.text_qa.async_text_qa_agent import AsyncTextQAAgent, async_text_qa_agent
from utils.constants import AgentType, TaskState, ErrorCode
from utils.exceptions import AgentNotFoundError, AgentCallError

# 创建异步路由器
async_router = APIRouter(prefix="/async", tags=["异步接口"])

# 搜索路由将在main.py中直接注册，不再通过async_router注册
# 这样可以使搜索API路径为 /api/v1/search 而不是 /api/v1/async/search


class AsyncTaskRequest(BaseModel):
    """异步任务请求模型"""
    task_id: str = Field(..., description="任务ID", example="async_task_001")
    task_type: str = Field("single", description="任务类型: single/multi", example="single")
    agent_type: str = Field(AgentType.TEXT_QA.value, description="Agent类型", example="text_qa")
    input: str = Field(..., description="任务输入", example="什么是异步编程？")
    priority: str = Field("normal", description="优先级: low/normal/high", example="normal")
    timeout: int = Field(30, description="超时时间(秒)", example=30)


class AsyncTaskResponse(BaseModel):
    """异步任务响应模型"""
    task_id: str
    status: str
    message: str
    result: Dict[str, Any] = Field(default_factory=dict)
    execution_time: float = 0.0


class BatchTaskRequest(BaseModel):
    """批量任务请求模型"""
    tasks: List[AsyncTaskRequest] = Field(..., description="任务列表")
    max_concurrent: int = Field(10, description="最大并发数", example=10)


class BatchTaskResponse(BaseModel):
    """批量任务响应模型"""
    batch_id: str
    total_tasks: int
    completed_tasks: int
    failed_tasks: int
    results: List[Dict[str, Any]]
    total_time: float = 0.0


# 全局异步编排器实例
async_orchestrator: AsyncOrchestratorAgent = None


async def get_async_orchestrator() -> AsyncOrchestratorAgent:
    """获取异步编排器实例（依赖注入）"""
    global async_orchestrator
    if async_orchestrator is None:
        async_orchestrator = AsyncOrchestratorAgent()
    return async_orchestrator


@async_router.post("/task/execute", response_model=AsyncTaskResponse)
async def execute_async_task(
    request: AsyncTaskRequest,
    orchestrator: AsyncOrchestratorAgent = Depends(get_async_orchestrator)
) -> AsyncTaskResponse:
    """
    执行异步任务
    
    特点：
    - 完全异步非阻塞
    - 支持并发Agent调用
    - 自动重试机制
    - 负载均衡选择最优实例
    """
    import time
    start_time = time.time()
    
    try:
        logger.info(f"收到异步任务请求: task_id={request.task_id}, type={request.task_type}")
        
        # 构建任务输入
        task_input = {
            "task_id": request.task_id,
            "task_type": request.task_type,
            "agent_type": request.agent_type,
            "input": request.input
        }
        
        # 异步执行任务（非阻塞）
        result = await asyncio.wait_for(
            orchestrator.execute_task_async(task_input),
            timeout=request.timeout
        )
        
        execution_time = time.time() - start_time
        
        if result["status"] == "success":
            logger.success(f"异步任务执行成功: task_id={request.task_id}, time={execution_time:.2f}s")
            return AsyncTaskResponse(
                task_id=request.task_id,
                status="success",
                message="任务执行成功",
                result=result,
                execution_time=execution_time
            )
        else:
            logger.error(f"异步任务执行失败: task_id={request.task_id}, error={result.get('error_msg')}")
            return AsyncTaskResponse(
                task_id=request.task_id,
                status="failed",
                message=result.get("error_msg", "任务执行失败"),
                result=result,
                execution_time=execution_time
            )
            
    except asyncio.TimeoutError:
        execution_time = time.time() - start_time
        logger.error(f"异步任务超时: task_id={request.task_id}, timeout={request.timeout}s")
        raise HTTPException(
            status_code=408,
            detail={
                "task_id": request.task_id,
                "error": f"任务执行超时(>{request.timeout}s)",
                "execution_time": execution_time
            }
        )
        
    except AgentNotFoundError as e:
        execution_time = time.time() - start_time
        logger.error(f"Agent未找到: task_id={request.task_id}, error={str(e)}")
        raise HTTPException(
            status_code=503,
            detail={
                "task_id": request.task_id,
                "error": "没有可用的Agent实例",
                "agent_type": request.agent_type,
                "execution_time": execution_time
            }
        )
        
    except Exception as e:
        execution_time = time.time() - start_time
        logger.error(f"异步任务执行异常: task_id={request.task_id}, error={str(e)}")
        raise HTTPException(
            status_code=500,
            detail={
                "task_id": request.task_id,
                "error": f"任务执行异常: {str(e)}",
                "execution_time": execution_time
            }
        )


@async_router.post("/task/batch", response_model=BatchTaskResponse)
async def execute_batch_tasks(
    request: BatchTaskRequest,
    background_tasks: BackgroundTasks,
    orchestrator: AsyncOrchestratorAgent = Depends(get_async_orchestrator)
) -> BatchTaskResponse:
    """
    批量执行异步任务
    
    特点：
    - 控制最大并发数，避免系统过载
    - 支持部分任务失败，不影响其他任务
    - 记录详细的执行统计信息
    """
    import time
    import uuid
    start_time = time.time()
    batch_id = f"batch_{uuid.uuid4().hex[:8]}"
    
    try:
        logger.info(f"收到批量任务请求: batch_id={batch_id}, total_tasks={len(request.tasks)}")
        
        # 构建批量任务输入
        task_inputs = []
        for task in request.tasks:
            task_input = {
                "task_id": task.task_id,
                "task_type": task.task_type,
                "agent_type": task.agent_type,
                "input": task.input
            }
            task_inputs.append(task_input)
        
        # 使用信号量控制并发数
        semaphore = asyncio.Semaphore(request.max_concurrent)
        
        async def execute_with_semaphore(task_input):
            async with semaphore:
                return await orchestrator.execute_task_async(task_input)
        
        # 并发执行所有任务
        results = await asyncio.gather(
            *[execute_with_semaphore(task_input) for task_input in task_inputs],
            return_exceptions=True
        )
        
        # 统计结果
        completed_tasks = 0
        failed_tasks = 0
        processed_results = []
        
        for i, result in enumerate(results):
            if isinstance(result, Exception):
                failed_tasks += 1
                error_result = {
                    "task_id": request.tasks[i].task_id,
                    "status": "failed",
                    "error": str(result)
                }
                processed_results.append(error_result)
            elif result.get("status") == "success":
                completed_tasks += 1
                processed_results.append(result)
            else:
                failed_tasks += 1
                processed_results.append(result)
        
        total_time = time.time() - start_time
        
        logger.success(
            f"批量任务执行完成: batch_id={batch_id}, "
            f"completed={completed_tasks}, failed={failed_tasks}, time={total_time:.2f}s"
        )
        
        return BatchTaskResponse(
            batch_id=batch_id,
            total_tasks=len(request.tasks),
            completed_tasks=completed_tasks,
            failed_tasks=failed_tasks,
            results=processed_results,
            total_time=total_time
        )
        
    except Exception as e:
        total_time = time.time() - start_time
        logger.error(f"批量任务执行异常: batch_id={batch_id}, error={str(e)}")
        raise HTTPException(
            status_code=500,
            detail={
                "batch_id": batch_id,
                "error": f"批量任务执行异常: {str(e)}",
                "total_time": total_time
            }
        )


@async_router.post("/text_qa/direct", response_model=Dict[str, Any])
async def direct_text_qa(
    request: Dict[str, Any]
) -> Dict[str, Any]:
    """
    直接调用异步文本问答Agent
    
    用于快速测试和简单场景，绕过编排器
    """
    import time
    start_time = time.time()
    
    try:
        task_id = request.get("task_id", f"direct_{int(time.time())}")
        query = request.get("query", "")
        user_id = request.get("user_id", "anonymous")
        
        if not query:
            raise HTTPException(status_code=400, detail="查询内容不能为空")
        
        logger.info(f"[DEBUG] 收到直接文本问答请求: request={request}")
        logger.info(f"[DEBUG] 处理请求参数: task_id={task_id}, query={query}, user_id={user_id}")
        
        # 构建任务
        task = {
            "task_id": task_id,
            "query": query,
            "user_id": user_id,
            "metadata": request.get("metadata", {})
        }
        
        logger.info(f"[DEBUG] 构建任务: {task}")
        
        # 异步处理任务
        logger.info("[DEBUG] 开始调用async_text_qa_agent.process_task_async")
        result = await async_text_qa_agent.process_task_async(task)
        logger.info(f"[DEBUG] 收到任务结果: {result}")
        
        execution_time = time.time() - start_time
        
        logger.success(f"直接文本问答完成: task_id={task_id}, time={execution_time:.2f}s")
        
        return {
            "task_id": task_id,
            "execution_time": execution_time,
            "result": result,
            "status": "success"
        }
        
    except Exception as e:
        execution_time = time.time() - start_time
        logger.error(f"直接文本问答异常: task_id={task_id}, error={str(e)}")
        raise HTTPException(
            status_code=500,
            detail={
                "task_id": task_id,
                "error": f"文本问答异常: {str(e)}",
                "execution_time": execution_time
            }
        )


@async_router.get("/performance/stats")
async def get_async_performance_stats() -> Dict[str, Any]:
    """
    获取异步接口性能统计
    
    包括：
    - 平均响应时间
    - 并发处理能力
    - 成功率统计
    """
    # 这里可以集成真实的性能监控数据
    # 目前返回模拟数据，实际项目中可以接入Prometheus等监控系统
    
    return {
        "async_performance": {
            "average_response_time_ms": 150,
            "max_concurrent_tasks": 100,
            "current_active_tasks": 5,
            "success_rate": 0.98,
            "total_tasks_processed": 1250,
            "failed_tasks": 25,
            "avg_task_execution_time": 0.8,
            "peak_throughput_per_second": 50
        },
        "agent_availability": {
            "text_qa": {"healthy_instances": 2, "total_instances": 3},
            "multi_modal": {"healthy_instances": 1, "total_instances": 2},
            "tool_call": {"healthy_instances": 3, "total_instances": 3}
        },
        "system_resources": {
            "cpu_usage_percent": 25.5,
            "memory_usage_mb": 512,
            "active_connections": 47
        }
    }


@async_router.get("/health")
async def async_health_check() -> Dict[str, Any]:
    """异步接口健康检查"""
    try:
        # 检查异步编排器状态
        orchestrator = await get_async_orchestrator()
        
        # 简单的连通性测试
        test_task = {
            "task_id": "health_check",
            "task_type": "single",
            "agent_type": AgentType.TEXT_QA.value,
            "input": "健康检查测试"
        }
        
        # 快速测试（2秒超时）
        result = await asyncio.wait_for(
            orchestrator.execute_task_async(test_task),
            timeout=2.0
        )
        
        return {
            "status": "healthy",
            "async_system": "running",
            "orchestrator": "active",
            "timestamp": time.time()
        }
        
    except Exception as e:
        logger.error(f"异步系统健康检查失败: {str(e)}")
        return {
            "status": "unhealthy",
            "async_system": "degraded",
            "error": str(e),
            "timestamp": time.time()
        }